package com.lqk.demo.jmm.exercise;

/**
 * @author lqk
 * @date 2021/12/28 20:11
 *
 * 问题1：枚举单例是如何限制实例个数的
 *  反编译后可以看出：
 *   // access flags 0x4019
 *   public final static enum Lcom/lqk/demo/jmm/exercise/Singleton2; INSTANCE
 *  就是一个单例模式，INSTANCE就是枚举类中的静态成员变量
 *
 * 问题2：枚举单例在创建时是否有并发问题
 *  没有：INSTANCE就是枚举类中的静态成员变量，就是在类加载过程中完成的
 *  是线程安全的
 * 问题3：枚举单例能否被反射破坏单例
 * 源码：
 * if ((clazz.getModifiers() & Modifier.ENUM) != 0)
 *              throw new IllegalArgumentException("Cannot reflectively create enum objects");
 *  不能，很强大，反射在通过newInstance创建对象时，会检查该类是否ENUM修饰，如果是则抛出异常，反射失败
 * 问题4：枚举单例能否被反序列化破坏单例
 *  可以，虽然Enum父类实现了序列化接口，但是考虑到这种情况，所以做了处理（解决序列化问题：transient和readObject。具体见：https://www.cnblogs.com/lanxuezaipiao/p/3369962.html）
 *  java 的transient关键字为我们提供了便利，你只需要实现Serilizable接口，将不需要序列化的属性前添加关键字transient，序列化对象的时候，这个属性就不会序列化到指定的目的地中。
 *      1）一旦变量被transient修饰，变量将不再是对象持久化的一部分，该变量内容在序列化后无法获得访问。
 *
 *      2）transient关键字只能修饰变量，而不能修饰方法和类。注意，本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量，则该类需要实现Serializable接口。
 *
 *      3）被transient关键字修饰的变量不再能被序列化，一个静态变量不管是否被transient修饰，均不能被序列化。
 * 问题5：枚举单例属于懒汉式还是饿汉式
 *  饿汉式？？？？？
 * 问题6：枚举单例如果希望加入一些单例创建时的初始化逻辑该如何做
 *  可以写一个构造方法，将初始化操作写到构造方法中
 */
public enum Singleton2 {
    INSTANCE;
}
